package com.meta.platform.area.service;

import com.google.common.collect.Lists;
import com.meta.platform.area.io.*;
import com.meta.platform.area.repository.AreasRepository;
import com.meta.platform.area.define.DistrictLevelEnum;
import com.meta.platform.area.domain.Areas;
import com.meta.platform.area.io.*;
import com.meta.platform.area.req.ro.AreasRo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 地区信息
 *
 * @Title: AreasQryServiceImpl
 * @Author: M.simple
 * @Remark: The modified content
 * @CreateDate: 2020-07-14 18:05:05
 * @Version: v2.0
 */
@Service
public class AreasQryServiceImpl implements AreasQryService {

	private AreasRepository areasRepository;

	@Autowired
	public AreasQryServiceImpl(AreasRepository areasRepository) {
		this.areasRepository = areasRepository;
	}
	@Override
	public Areas queryProvince(Long provinceId) {
		Areas area = areasRepository.getAreas(provinceId);
		if (area != null) {
			if (area.getLevel() == 1) {
				return area;
			} else {
				return this.queryProvince(area.getParentId());
			}
		} else {
			return area;
		}
	}

	@Override
	public Areas queryCity(Long cityId) {
		Areas area = areasRepository.getAreas(cityId);
		if (area != null) {
			if (area.getLevel() == 2) {
				return area;
			} else {
				return this.queryCity(area.getParentId());
			}
		} else {
			return area;
		}
	}

	@Override
	public Areas queryCounty(Long countyId) {
		return areasRepository.getAreas(countyId);
	}

	@Override
	public String queryAddress(Long countyId, List<Areas> areas) {
		if (countyId == null) {
			return "";
		}
		if (areas == null) {
			areas = new ArrayList<Areas>();
		}
		Areas area = areasRepository.getAreas(countyId);
		if (area != null) {
			areas.add(area);
			if (area.getParentId().longValue() == 0) {
				String address = "";
				for (int i = areas.size(); i > 0; i--) {// areas 区县 市级 省级
					address += areas.get(i - 1).getAreaName() + " ";
				}
				return address;
			} else {
				return this.queryAddress(area.getParentId(), areas);
			}
		} else {
			return "";
		}
	}

	@Override
	public String queryFullAddress(Long areaId) {
		List<Areas> areas = new ArrayList<Areas>();
		return queryAddress(areaId, areas);
	}

	@Override
	public List<Long> queryFullAddressIds(Long areaId) {
		List<Long> areaIdList = areasRepository.queryFullAreaId(areaId);
		return areaIdList;
	}

	private void createAreaTree(AreaTree treeNode, List<Areas> areaList) {
		List<AreaTree> childTreeNode = new ArrayList<>();
		for (int i = 0, l = areaList.size(); i < l; i++) {
			if (treeNode.getArea().getAreaId().equals(areaList.get(i).getParentId())) {
				AreaTree areaTree = new AreaTree(areaList.get(i));
				createAreaTree(areaTree, areaList);
				childTreeNode.add(areaTree);
			}
			treeNode.setChildTree(childTreeNode);
		}
	}

	@Override
	public AreaTree queryAreaTree(Long areaId) {
		List<Areas> areaList = areasRepository.queryAllArea();
		if (areaList != null && !areaList.isEmpty()) {
			Areas rootArea = new Areas();
			rootArea.setAreaId(areaId);
			AreaTree rootNode = new AreaTree(rootArea);
			createAreaTree(rootNode, areaList);
			return rootNode;
		}
		return null;

	}

	private void getChildrenAreaIdFromTree(AreaTree areaTree, Set<Long> areaIdsSet, Long areaId) {
		if (!areaTree.getArea().getParentId().equals(areaId)) {
			for (AreaTree childareaTree : areaTree.getChildTree()) {
				getChildrenAreaIdFromTree(childareaTree, areaIdsSet, areaId);
			}
		} else {
			for (AreaTree childareaTree : areaTree.getChildTree()) {
				getChildrenAreaIdFromTree(childareaTree, areaIdsSet, areaTree.getArea().getAreaId());
			}
			areaIdsSet.add(areaTree.getArea().getAreaId());
		}

	}

	@Override
	public Set<Long> getChildrenAreaId(List<Long> areaIds) {
		AreaTree areaTree = queryAreaTree(0l);
		areaTree.getArea().setParentId(0l);
		Set<Long> areaIdsSet = new HashSet<>();
		for (Long areaId : areaIds) {
			getChildrenAreaIdFromTree(areaTree, areaIdsSet, areaId);
		}

		return areaIdsSet;
	}


	/* 找到一颗树中某个节点 */
	@Override
	public AreaTree findAreaTreeById(AreaTree areaTree, Long nodeId) {
		if (areaTree.getArea().getAreaId().equals(nodeId)) {
			return areaTree;
		}
		if (areaTree.getChildTree() == null || areaTree.getChildTree().isEmpty()) {
			return null;
		} else {
			int childNumber = areaTree.getChildTree().size();
			for (int i = 0; i < childNumber; i++) {
				AreaTree child = areaTree.getChildTree().get(i);
				AreaTree resultNode = findAreaTreeById(child, nodeId);
				if (resultNode != null) {
					return resultNode;
				}
			}
			return null;
		}
	}

	/* 返回当前节点的晚辈集合 */
	@Override
	public List<AreaTree> getJuniors(AreaTree areaTree) {
		List<AreaTree> juniorList = new ArrayList<AreaTree>();
		List<AreaTree> childList = areaTree.getChildTree();
		if (childList == null) {
			return juniorList;
		} else {
			int childNumber = childList.size();
			for (int i = 0; i < childNumber; i++) {
				AreaTree junior = childList.get(i);
				juniorList.add(junior);
				juniorList.addAll(getJuniors(junior));
			}
			return juniorList;
		}
	}

	@Override
	public List<Areas> queryAllArea() {
		return areasRepository.queryAllArea();
	}

	@Override
	public List<Areas> getParentArea(Long childId) {
		Map<Long, Areas> childParentAreaMap = getChildParentAreaMap();
		return getParentArea(childId, childParentAreaMap);
	}

	@Override
	public List<Areas> getParentArea(Long childId, Map<Long, Areas> childParentAreaMap) {

		List<Areas> areaList = new ArrayList<Areas>();
		getParentAreaRepeat(areaList, childId, childParentAreaMap);

		return areaList;
	}

	@Override
	public String getFullAddress(Long childId, List<Areas> areaAllList) {
		if (null == childId || null == areaAllList || 0 == areaAllList.size()) {
			return "";
		}

		/**
		 * key : 区域id,value : 区域对象
		 */
		Map<Long, Areas> areaMap = new HashMap<Long, Areas>();
		for (Areas item : areaAllList) {
			areaMap.put(item.getAreaId(), item);
		}

		/**
		 * key ：区域id, value ： 父对象
		 */
		Map<Long, Areas> childParentMap = new HashMap<Long, Areas>();
		for (Areas item : areaAllList) {
			Long parentId = item.getParentId();
			Areas areaParent = areaMap.get(parentId);
			if (null != areaParent) {
				childParentMap.put(item.getAreaId(), areaParent);
			}
		}

		List<Areas> areaList = getParentArea(childId, childParentMap);

		// 把当前地域节点加入进去
		Areas areaCur = areaMap.get(childId);
		if (null != areaCur) {
			areaList.add(areaCur);
		}

		StringBuffer buffer = new StringBuffer();
		for (Areas areaItem : areaList) {
			buffer.append(areaItem.getAreaName());
		}
		return buffer.toString();
	}

	private void getParentAreaRepeat(List<Areas> areaList, Long childId, Map<Long, Areas> childParentAreaMap) {

		Areas area = childParentAreaMap.get(childId);
		if (null != area) {
			areaList.add(0, area);
			getParentAreaRepeat(areaList, area.getAreaId(), childParentAreaMap);
		}
	}

	@Override
	public Map<Long, Areas> getChildParentAreaMap() {
		List<Areas> areaList = queryAllArea();

		/**
		 * key : 区域id,value : 区域对象
		 */
		Map<Long, Areas> areaMap = new HashMap<Long, Areas>();
		for (Areas item : areaList) {
			areaMap.put(item.getAreaId(), item);
		}

		/**
		 * key ：区域id, value ： 父对象
		 */
		Map<Long, Areas> childParentMap = new HashMap<Long, Areas>();
		for (Areas item : areaList) {
			Long parentId = item.getParentId();
			Areas areaParent = areaMap.get(parentId);
			if (null != areaParent) {
				childParentMap.put(item.getAreaId(), areaParent);
			}
		}
		return childParentMap;
	}

	@Override
	public List<Province> queryAllAddress() {
		return areasRepository.queryAddress();
	}

	/**
	 * batch list Area info
	 * @method      batchListArea
	 * @param       areaIdList:
	 * @return      List<Areas>
	 * @author      M.simple
	 * @date        2020/8/6 5:54 下午
	 * @version     v2.0
	 */
	@Override
	public List<Areas> batchListArea(List<Long> areaIdList){

		AreasRo areasRo = AreasRo.builder().build();
		areasRo.setAreaIdList(areaIdList);
		
		return areasRepository.listAreas(areasRo);
	}

	@Override
	public List<District> listDistrict(Long cityId) {

		List<District> districts = Lists.newArrayList();
		
		List<AreaDistrictIo> areaDistrictIos = listNextLevelArea(cityId, null);
		areaDistrictIos = Optional.ofNullable(areaDistrictIos).orElse(Lists.newArrayList());
		areaDistrictIos.forEach(districtArea -> {
			District district = District.builder().districtId(districtArea.getAreaId()).districtName(districtArea.getAreaName()).build();
			districts.add(district);
		});

		return districts;
	}

	/**
	 * list all level area info province-city-dintrict
	 *
	 * @param :
	 * @return
	 * @method listLevelArea
	 * @author M.simple
	 * @date 2020/7/29 2:05 下午
	 * @version v2.0
	 */
	@Override
	public List<Province> listAllLevelArea(Integer level) {

		if (Objects.isNull(level)) {
			level = DistrictLevelEnum.DISTRICT.getLevelId();
		}

		List<Areas> areasList = areasRepository.listEffectiveAreas(AreasRo.builder().build());
		List<Province> provinceList = Lists.newArrayList();
		Map<Long, List<Areas>> cityMap = areasList.stream().collect(Collectors.groupingBy(Areas::getParentId));
		if (level >= DistrictLevelEnum.PROVINCE.getLevelId()) {
			Integer finalLevel = level;
			areasList.stream().filter(x -> DistrictLevelEnum.PROVINCE.getLevelId().equals(x.getLevel())).forEach(areas -> {
				Province province = Province.builder().provinceId(areas.getAreaId()).provinceName(areas.getAreaName()).build();
				List<Areas> provinceCityList = cityMap.get(areas.getAreaId());
				List<City> cityList = Lists.newArrayList();
				provinceCityList = Optional.ofNullable(provinceCityList).orElse(Lists.newArrayList());
				if (finalLevel >= DistrictLevelEnum.CITY.getLevelId()) {
					provinceCityList.forEach(cityArea -> {
						City city = City.builder().cityId(cityArea.getAreaId()).cityName(cityArea.getAreaName()).build();
						List<Areas> districtList = cityMap.get(cityArea.getAreaId());
						List<District> districts = Lists.newArrayList();
						districtList = Optional.ofNullable(districtList).orElse(Lists.newArrayList());
						if (finalLevel >= DistrictLevelEnum.DISTRICT.getLevelId()) {
							districtList.forEach(districtArea -> {
								District district = District.builder().districtId(districtArea.getAreaId()).districtName(districtArea.getAreaName()).build();
								districts.add(district);
							});
						}
						city.setDistrictList(districts);
						cityList.add(city);
					});
				}
				province.setCityList(cityList);
				provinceList.add(province);
			});
		}
		//Map<Long, List<Areas>> districtMap = areasList.stream().filter(x -> DistrictLevelEnum.DISTRICT.getLevelId().equals(x.getLevel())).collect(Collectors.groupingBy(Areas::getParentId));

		return provinceList;
	}

	/**
	 * 获取区域信息
	 *
	 * @param areaId:
	 * @return Areas
	 * @method getAreaByAreaId
	 * @author M.simple
	 * @date 2020/7/29 10:47 上午
	 * @version v2.0
	 */
	@Override
	public Areas getAreaByAreaId(Long areaId) {

		AreasRo areas = AreasRo.builder().build();
		areas.setAreaId(areaId);
		List<Areas> areasList = areasRepository.listAreas(areas);
		if (Optional.ofNullable(areasList).isPresent()) {
			return areasList.get(0);
		}
		return null;
	}

	/**
	 * 查询下一节点区域信息
	 *
	 * @param parentId:
	 * @return List<AreaDistrictIo>
	 * @method listNextLevelArea
	 * @author M.simple
	 * @date 2020/7/28 8:05 下午
	 * @version v2.0
	 */
	@Override
	public List<AreaDistrictIo> listNextLevelArea(Long parentId, String keyword) {

		List<AreaDistrictIo> areaDistrictIos = Lists.newArrayList();

		AreasRo areasRo = AreasRo.builder().build();
		areasRo.setParentId(parentId);
		areasRo.setKeyword(keyword);
		List<Areas> areas = areasRepository.listEffectiveAreas(areasRo);
		areas.forEach(areasInfo -> {
			AreaDistrictIo areaDistrictIo = AreaDistrictIo.builder().areaId(areasInfo.getAreaId()).areaName(areasInfo.getAreaName())
					.level(areasInfo.getLevel()).build();

			areaDistrictIos.add(areaDistrictIo);
		});

		return areaDistrictIos;
	}

	/**
	 * list Areas info
	 *
	 * @param areas:
	 * @return List<Areas>
	 * @method listAreas
	 * @author M.simple
	 * @date 2020-07-14 18:05:05
	 */
	@Override
	public List<Areas> listAreas(AreasRo areas) {
		return areasRepository.listAreas(areas);
	}

}
